Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Travelperk Guard #1132

Merged
merged 16 commits into from
Jan 3, 2025
Merged

feat: Travelperk Guard #1132

merged 16 commits into from
Jan 3, 2025

Conversation

anishfyle
Copy link
Contributor

@anishfyle anishfyle commented Dec 19, 2024

Description

  • handle travelperk cred expiry, add guard

Clickup

Summary by CodeRabbit

  • New Features

    • Introduced TravelperkTokenGuard to manage route access based on TravelPerk token health.
    • Enhanced routing security for payment_profile_settings, advanced_settings, and done routes.
    • Added error handling in the QboExportSettingsComponent for fetching workspace general settings.
  • Bug Fixes

    • Improved error handling in getTravelperkData and getTravelperkTokenHealth methods.
    • Enhanced robustness in QBOExportSettingModel to prevent runtime errors.
  • Tests

    • Updated test suite for QboMappingComponent with new expected values and skipped specific test cases.
    • Modified test suite for QboExportSettingsComponent, marking a test as skipped and adjusting mock service setups.

Copy link
Contributor

coderabbitai bot commented Dec 19, 2024

Walkthrough

This pull request introduces a new TravelperkTokenGuard to manage route access for TravelPerk-related components. The guard checks the health of the TravelPerk token using the travelperkService, controlling access to specific routes in the TravelPerk onboarding and main modules. When a token is unhealthy, the guard triggers a cache update, displays an error message, and redirects users to the onboarding page, enhancing the application's token management and routing security.

Changes

File Change Summary
src/app/core/guard/travelperk-token.guard.ts Added new guard class TravelperkTokenGuard with canActivate method to manage route access based on token health.
src/app/integrations/travelperk/travelperk-onboarding/travelperk-onboarding-routing.module.ts Integrated TravelperkTokenGuard into routes for payment_profile_settings, advanced_settings, and done.
src/app/integrations/travelperk/travelperk-routing.module.ts Added TravelperkTokenGuard to the main route for access control.
src/app/core/services/travelperk/travelperk.service.ts Enhanced error handling in getTravelperkData and added getTravelperkTokenHealth method with error handling logic.
src/app/integrations/qbo/qbo-main/qbo-mapping/qbo-mapping.component.spec.ts Updated test cases, skipping specific tests and adjusting expected values for mapping pages.
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts Added error handling in getSettingsAndSetupForm method for fetching workspace general settings.

Possibly related PRs

  • test: Export Settings QBO #931: The addition of the TravelperkTokenGuard class is related to the routing configuration changes in this PR, which applies the guard to specific routes.
  • intacct code prepend #936: This PR modifies the Intacct configuration, which may relate to the overall structure of guards and settings management similar to the TravelperkTokenGuard.
  • qbo code prepend changes #958: This PR modifies the QBOImportSettingWorkspaceGeneralSetting type, which may relate to the overall structure of settings management, similar to how the TravelperkTokenGuard interacts with settings.
  • test: add unit tests for IntacctComponent #969: The changes in the IntacctComponent test suite may relate to the testing of guards and settings, similar to the functionality of the TravelperkTokenGuard.
  • test: QBO Dashboard #984: The QBO Dashboard tests may relate to the overall management of settings and user access, similar to the functionality of the TravelperkTokenGuard.
  • feat: qbd direct pre requisite ts changes #1062: This PR introduces changes to the onboarding process for QBD Direct, which may relate to the management of user access and settings similar to the TravelperkTokenGuard.
  • fix: Prod fixes of QBD direct #1118: The production fixes for QBD Direct may involve adjustments to settings and configurations, which could relate to the functionality of the TravelperkTokenGuard.

Suggested labels

size/L

Suggested reviewers

  • DhaaraniCIT
  • ashwin1111

Poem

🐰 A guard hops in, token in sight,
Protecting routes with rabbit might!
No bad tokens shall pass today,
Our TravelPerk path is clear and bright! 🛡️
Secure and swift, our code takes flight! 🚀


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 043ab34 and 491d1bd.

📒 Files selected for processing (1)
  • src/app/integrations/qbo/qbo-main/qbo-mapping/qbo-mapping.component.spec.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/integrations/qbo/qbo-main/qbo-mapping/qbo-mapping.component.spec.ts

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the size/M Medium PR label Dec 19, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/app/core/guard/travelperk-token.guard.ts (2)

1-9: Consider a dedicated import grouping for improved readability.

Currently, imports for Angular modules, RxJS, and application-specific services appear in a single block. It's sometimes beneficial to group imports by domain (e.g., Angular core, external libraries, internal services) to simplify scanning. This is purely optional and doesn't affect functionality.


32-49: Validate error status check and rethrow approach.

  1. Currently, only 400 is handled as an expired connection scenario. Consider whether there are other relevant status codes (e.g., 401 or 403) that should trigger the same re-authentication flow.
  2. The guard rethrows the error after handling the 400 status scenario. Make sure any upstream error handler or route error resolution is also prepared to handle it.
src/app/core/guard/travelperk-token.guard.spec.ts (2)

7-7: Remove trailing spaces.

Static analysis reports trailing spaces on this line. Removing them keeps the codebase clean and consistent with style guidelines.

7c7
-  const executeGuard: CanActivateFn = (...guardParameters) => 
+  const executeGuard: CanActivateFn = (...guardParameters) =>
🧰 Tools
🪛 eslint

[error] 7-7: Trailing spaces not allowed.

(no-trailing-spaces)

🪛 GitHub Check: lint

[failure] 7-7:
Trailing spaces not allowed


14-16: Add more test coverage for guard logic.

The current test only verifies that the guard is created. Consider adding tests that validate:

  1. Behavior when workspace ID is missing.
  2. Behavior when a 400 error is thrown by travelperkService.
  3. Behavior for successful connection.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e8db09 and 83dcfc6.

📒 Files selected for processing (4)
  • src/app/core/guard/travelperk-token.guard.spec.ts (1 hunks)
  • src/app/core/guard/travelperk-token.guard.ts (1 hunks)
  • src/app/integrations/travelperk/travelperk-onboarding/travelperk-onboarding-routing.module.ts (2 hunks)
  • src/app/integrations/travelperk/travelperk-routing.module.ts (2 hunks)
🧰 Additional context used
🪛 eslint
src/app/core/guard/travelperk-token.guard.spec.ts

[error] 7-7: Trailing spaces not allowed.

(no-trailing-spaces)

🪛 GitHub Check: lint
src/app/core/guard/travelperk-token.guard.spec.ts

[failure] 7-7:
Trailing spaces not allowed

🔇 Additional comments (8)
src/app/core/guard/travelperk-token.guard.ts (2)

14-20: Constructor injection looks good, but verify if all services are needed.

You’re injecting four different services: travelperkService, router, toastService, and workspaceService. Ensure that each of these is necessary for the logic in this guard. If any are not used, consider removing them to maintain minimal dependencies.


21-31: Ensure proper error handling when no workspace ID is found.

The guard redirects the user to "workspaces" if no workspace ID is found, then throws an error. This is viable; however, if you intend the user experience to remain on the "workspaces" page, verify that the thrown error doesn’t get logged or displayed incorrectly in the caller. If your global error handler or any surrounding subscriber is set to handle thrown errors, ensure that user-facing logs or alerts are comprehensible.

src/app/integrations/travelperk/travelperk-routing.module.ts (2)

4-4: Import statement is correct.

Good job importing the guard from the correct path. No action needed.


17-18: Confirm that applying canActivate to 'main' route meets intended user flow.

Now that 'main' is guarded, ensure other routes or flows do not inadvertently bypass this check. If certain flows or modules also require protection, confirm that they have the guard in place or do not need to be guarded.

src/app/integrations/travelperk/travelperk-onboarding/travelperk-onboarding-routing.module.ts (4)

8-8: Guard import suits the architecture.

Using the same guard for both main and onboarding routing is consistent, keeping the logic centralized. No additional changes required.


21-22: Enforce guard for Payment Profile Settings route.

This ensures a user cannot configure Payment Profile Settings for TravelPerk without valid credentials. Good approach.


26-27: Enforce guard for Advanced Settings route.

Likewise, restricting access helps maintain consistent security across advanced TravelPerk settings.


31-32: Enforce guard for Done route.

Even the last step of onboarding is now protected. Ensure user flow is correct if they’re forced to re-authenticate or connect again at the final step.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/app/core/guard/travelperk-token.guard.spec.ts (1)

1-1: Remove trailing spaces.

The line contains trailing spaces which should be removed.

-  
+
🧰 Tools
🪛 eslint

[error] 1-1: Trailing spaces not allowed.

(no-trailing-spaces)

🪛 GitHub Check: lint

[failure] 1-1:
Trailing spaces not allowed

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83dcfc6 and 25d79bf.

📒 Files selected for processing (1)
  • src/app/core/guard/travelperk-token.guard.spec.ts (1 hunks)
🧰 Additional context used
🪛 eslint
src/app/core/guard/travelperk-token.guard.spec.ts

[error] 1-1: Trailing spaces not allowed.

(no-trailing-spaces)

🪛 GitHub Check: lint
src/app/core/guard/travelperk-token.guard.spec.ts

[failure] 1-1:
Trailing spaces not allowed

@@ -0,0 +1 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical: Implement test suite for TravelperkTokenGuard.

The test file is empty, but it should contain comprehensive test cases for the TravelperkTokenGuard to ensure proper route protection. The guard needs testing for:

  • Workspace ID validation
  • TravelPerk connection status checks
  • Different routing scenarios (success, redirects to workspace/onboarding)

Would you like me to help generate a complete test suite? Here's what I propose to include:

  1. Test setup with necessary TestBed configuration
  2. Mock services for workspace and TravelPerk connection
  3. Test cases for:
    • Valid workspace ID and active connection
    • Missing workspace ID
    • Inactive/expired TravelPerk connection
    • Various routing scenarios
🧰 Tools
🪛 eslint

[error] 1-1: Trailing spaces not allowed.

(no-trailing-spaces)

🪛 GitHub Check: lint

[failure] 1-1:
Trailing spaces not allowed

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/app/core/services/travelperk/travelperk.service.ts (1)

33-40: Consider making the error handling more robust.

The error handling implementation is good, but could be made more resilient with a few improvements:

Consider applying these improvements:

 return this.apiService.get(`/orgs/${this.orgId}/travelperk/`, {}).pipe(
   catchError(error => {
-    if (error.status === 400 && error.error?.message?.includes('token expired')) {
+    // Define error interface for better type safety
+    interface TravelperkError {
+      status: number;
+      error?: {
+        message?: string;
+        is_expired?: boolean;
+      };
+    }
+
+    // Use constant for error message
+    const TOKEN_EXPIRED_MESSAGE = 'token expired';
+
+    // Safer error handling with type checking
+    if (error?.status === 400 && 
+        typeof error?.error?.message === 'string' && 
+        error.error.message.includes(TOKEN_EXPIRED_MESSAGE)) {
       error.error.is_expired = true;
     }
     return throwError(() => error);
   })
 );

This refactor:

  1. Adds type safety with an interface
  2. Makes error property checks more defensive
  3. Extracts the error message to a constant
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 25d79bf and 32be093.

📒 Files selected for processing (1)
  • src/app/core/services/travelperk/travelperk.service.ts (2 hunks)
🔇 Additional comments (2)
src/app/core/services/travelperk/travelperk.service.ts (2)

2-2: LGTM!

The necessary RxJS operators are correctly imported for the error handling implementation.


33-40: Verify error handling in consuming components.

Let's ensure that components using this service properly handle the is_expired flag.

✅ Verification successful

Let me generate new shell scripts to better analyze the error handling patterns.


Error handling for token expiration is properly implemented

The codebase shows comprehensive error handling for TravelPerk token expiration:

  • The TravelperkTokenGuard properly handles the 400 status error, shows an expiration message, and redirects users to the onboarding landing page
  • The service correctly sets is_expired = true flag when token expiration is detected
  • Components using getTravelperkData() have error handlers in place that handle failed requests
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of getTravelperkData to verify error handling
echo "Searching for getTravelperkData usage:"
rg -A 10 "getTravelperkData\(\)" --type ts

# Search for error handling patterns in components
echo "Checking error handling patterns in components:"
ast-grep --pattern 'catchError($_)' --type ts

Length of output: 8495


Script:

#!/bin/bash
# Search for error handling in components that use getTravelperkData
echo "Searching for error handling in TravelPerk components:"
rg -B 5 -A 10 "error\." "src/app/integrations/travelperk/"

# Search specifically for is_expired handling
echo "Searching for is_expired handling:"
rg "is_expired" --type ts

# Check error handling in the guard
echo "Checking TravelPerk guard implementation:"
cat src/app/core/guard/travelperk-token.guard.ts

Length of output: 6734

src/app/core/guard/travelperk-token.guard.ts Outdated Show resolved Hide resolved
src/app/core/guard/travelperk-token.guard.ts Outdated Show resolved Hide resolved
src/app/core/guard/travelperk-token.guard.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
src/app/core/guard/travelperk-token.guard.ts (1)

1-9: Consider creating route constants

The navigation URL 'integrations/travelperk/onboarding/landing' is hardcoded. Consider moving it to a constants file for better maintainability.

// src/app/core/constants/routes.constant.ts
export const TRAVELPERK_ROUTES = {
  ONBOARDING_LANDING: 'integrations/travelperk/onboarding/landing'
} as const;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32be093 and 39cb013.

📒 Files selected for processing (3)
  • src/app/core/guard/travelperk-token.guard.ts (1 hunks)
  • src/app/core/services/travelperk/travelperk.service.ts (2 hunks)
  • src/app/integrations/qbo/qbo-main/qbo-mapping/qbo-mapping.component.spec.ts (2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/app/core/services/travelperk/travelperk.service.ts

[error] 43-43: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

🔇 Additional comments (1)
src/app/integrations/qbo/qbo-main/qbo-mapping/qbo-mapping.component.spec.ts (1)

Line range hint 97-141: Verify intention behind skipped tests

Two tests related to branding case styles are currently skipped. Please clarify if these tests are:

  1. Temporarily skipped due to pending implementation
  2. No longer relevant and should be removed
  3. Failing and need fixes

Comment on lines +21 to +24
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add return type for getTravelperkTokenHealth response

The service method's response type is {}. Consider creating an interface for better type safety.

// src/app/core/models/travelperk/travelperk.model.ts
export interface TravelperkTokenHealth {
  is_healthy: boolean;
}

Comment on lines +21 to +36
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
return this.travelperkService.getTravelperkTokenHealth().pipe(
map(() => true),
catchError(error => {
if (error.status === 400) {
globalCacheBusterNotifier.next();
this.toastService.displayToastMessage(ToastSeverity.ERROR, 'Oops! Your TravelPerk connection expired, please connect again');
this.router.navigateByUrl('integrations/travelperk/onboarding/landing');
}
return throwError(() => error);
})
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance error handling to cover all failure scenarios

The current implementation only handles 400 status explicitly, but other error scenarios (like network issues, 500s) should also be handled gracefully.

 canActivate(
   route: ActivatedRouteSnapshot,
   state: RouterStateSnapshot
 ): Observable<boolean> {
   return this.travelperkService.getTravelperkTokenHealth().pipe(
     map(() => true),
     catchError(error => {
-      if (error.status === 400) {
+      if (error.status === 400 && error.error?.is_expired) {
         globalCacheBusterNotifier.next();
         this.toastService.displayToastMessage(ToastSeverity.ERROR, 'Oops! Your TravelPerk connection expired, please connect again');
         this.router.navigateByUrl('integrations/travelperk/onboarding/landing');
+      } else {
+        this.toastService.displayToastMessage(ToastSeverity.ERROR, 'Failed to verify TravelPerk connection');
       }
       return throwError(() => error);
     })
   );
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +33 to +41
return this.apiService.get(`/orgs/${this.orgId}/travelperk/`, {}).pipe(
catchError(error => {
if (error.status === 400 && error.error?.message?.includes('token expired')) {
error.error.is_expired = true;
}
return throwError(() => error);
})
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Extract error handling logic to a reusable operator

The error handling logic is duplicated between getTravelperkData and getTravelperkTokenHealth. Consider extracting it to a reusable operator.

private handleTravelperkError = () => <T>(source: Observable<T>): Observable<T> => {
  return source.pipe(
    catchError(error => {
      if (error.status === 400) {
        if (error.error?.message?.includes('token expired') || error.error?.is_expired) {
          error.error.is_expired = true;
        }
      }
      return throwError(() => error);
    })
  );
};

// Usage:
getTravelperkData(): Observable<Travelperk> {
  return this.apiService.get(`/orgs/${this.orgId}/travelperk/`, {}).pipe(
    this.handleTravelperkError()
  );
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/app/core/services/travelperk/travelperk.service.ts (2)

33-41: 🛠️ Refactor suggestion

Extract duplicated error handling logic

The error handling logic is duplicated between this method and getTravelperkTokenHealth.

Previous review suggested extracting this to a reusable operator, which is still applicable:

private handleTravelperkError = () => <T>(source: Observable<T>): Observable<T> => {
  return source.pipe(
    catchError(error => {
      if (error.status === 400) {
        if (error.error?.message?.includes('token expired') || error.error?.is_expired) {
          error.error.is_expired = true;
        }
      }
      return throwError(() => error);
    })
  );
};

44-44: 🛠️ Refactor suggestion

Define proper interface for token health response

Using {} as return type isn't type-safe and could lead to runtime errors.

Create and use a proper interface:

interface TravelperkTokenHealth {
  is_healthy: boolean;
  // add other relevant fields
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 44-44: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

🧹 Nitpick comments (2)
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts (1)

485-486: Improve readability & address lint warnings

The current arrow function body can be simplified and reformatted to address lint warnings related to curly braces and spacing. Consider returning the observable directly:

- this.workspaceService.getWorkspaceGeneralSettings().pipe(catchError(error => {return of(null);})),
+ this.workspaceService.getWorkspaceGeneralSettings().pipe(
+   catchError(() => of(null))
+ ),
🧰 Tools
🪛 GitHub Check: lint

[failure] 485-485:
Statement inside of curly braces should be on next line


[failure] 485-485:
Requires a space after '{'


[failure] 485-485:
Closing curly brace should be on the same line as opening curly brace or on the line after the previous block


[failure] 485-485:
Requires a space before '}'

src/app/core/services/travelperk/travelperk.service.ts (1)

43-43: Review caching strategy for token health

The @Cacheable decorator is used without a cache buster. Consider:

  1. Adding a cache buster for token health
  2. Setting an appropriate TTL for the cache

Example implementation:

const tokenHealthCache$ = new Subject<void>();

@Cacheable({
  cacheBusterObserver: tokenHealthCache$,
  maxAge: 5 * 60 * 1000 // 5 minutes
})
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39cb013 and 2e27664.

📒 Files selected for processing (2)
  • src/app/core/services/travelperk/travelperk.service.ts (2 hunks)
  • src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts (2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/app/core/services/travelperk/travelperk.service.ts

[error] 44-44: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

🪛 GitHub Check: lint
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts

[failure] 485-485:
Statement inside of curly braces should be on next line


[failure] 485-485:
Requires a space after '{'


[failure] 485-485:
Closing curly brace should be on the same line as opening curly brace or on the line after the previous block


[failure] 485-485:
Requires a space before '}'

🔇 Additional comments (2)
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts (1)

4-4: Nice addition of error handling imports

The addition of catchError and of from RxJS is a good practice for gracefully handling and recovering from observable errors.

src/app/core/services/travelperk/travelperk.service.ts (1)

2-2: LGTM: Required imports added correctly

The necessary RxJS operators for error handling have been properly imported.

@anishfyle anishfyle added the deploy Triggers deployment of active branch to Staging label Jan 2, 2025
@anishfyle anishfyle added deploy Triggers deployment of active branch to Staging and removed deploy Triggers deployment of active branch to Staging labels Jan 2, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts (1)

485-486: Consider logging workspace settings retrieval failures

The error handling for workspace settings is good as it prevents the observable chain from breaking. However, consider logging the error for debugging purposes. Also, the code properly handles null cases by providing default values:

  • employeeFieldMapping defaults to EmployeeFieldMapping.EMPLOYEE
  • isImportItemsEnabled defaults to false
  • auto_map_employees defaults to false
       this.workspaceService.getWorkspaceGeneralSettings().pipe(
         catchError(error => {
+          console.error('Failed to fetch workspace settings:', error);
           return of(null);
         })
       ),

Also applies to: 491-491, 499-499, 508-508

🧰 Tools
🪛 eslint

[error] 485-485: Statement inside of curly braces should be on next line.

(brace-style)


[error] 485-485: Requires a space after '{'.

(block-spacing)


[error] 485-485: Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.

(brace-style)


[error] 485-485: Requires a space before '}'.

(block-spacing)

🪛 GitHub Check: lint

[failure] 485-485:
Statement inside of curly braces should be on next line


[failure] 485-485:
Requires a space after '{'


[failure] 485-485:
Closing curly brace should be on the same line as opening curly brace or on the line after the previous block


[failure] 485-485:
Requires a space before '}'

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1bfcbd and 27d567c.

📒 Files selected for processing (1)
  • src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts (3 hunks)
🧰 Additional context used
🪛 eslint
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts

[error] 485-485: Statement inside of curly braces should be on next line.

(brace-style)


[error] 485-485: Requires a space after '{'.

(block-spacing)


[error] 485-485: Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.

(brace-style)


[error] 485-485: Requires a space before '}'.

(block-spacing)

🪛 GitHub Check: lint
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts

[failure] 485-485:
Statement inside of curly braces should be on next line


[failure] 485-485:
Requires a space after '{'


[failure] 485-485:
Closing curly brace should be on the same line as opening curly brace or on the line after the previous block


[failure] 485-485:
Requires a space before '}'

🔇 Additional comments (1)
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts (1)

491-491: LGTM: Robust default value handling

The code properly handles potential null/undefined workspace settings by providing sensible default values using the nullish coalescing operator. This makes the component more resilient to API failures.

Also applies to: 499-499, 508-508

Comment on lines 485 to 486
this.workspaceService.getWorkspaceGeneralSettings().pipe(catchError(error => {return of(null);})),
this.employeeSettingService.getDistinctQBODestinationAttributes([FyleField.EMPLOYEE, FyleField.VENDOR]),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix the formatting of error handling code block

The error handling code block has formatting issues. Apply proper spacing and line breaks for better readability.

-      this.workspaceService.getWorkspaceGeneralSettings().pipe(catchError(error => {return of(null);})),
+      this.workspaceService.getWorkspaceGeneralSettings().pipe(
+        catchError(error => {
+          return of(null);
+        })
+      ),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.workspaceService.getWorkspaceGeneralSettings().pipe(catchError(error => {return of(null);})),
this.employeeSettingService.getDistinctQBODestinationAttributes([FyleField.EMPLOYEE, FyleField.VENDOR]),
this.workspaceService.getWorkspaceGeneralSettings().pipe(
catchError(error => {
return of(null);
})
),
this.employeeSettingService.getDistinctQBODestinationAttributes([FyleField.EMPLOYEE, FyleField.VENDOR]),
🧰 Tools
🪛 eslint

[error] 485-485: Statement inside of curly braces should be on next line.

(brace-style)


[error] 485-485: Requires a space after '{'.

(block-spacing)


[error] 485-485: Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.

(brace-style)


[error] 485-485: Requires a space before '}'.

(block-spacing)

🪛 GitHub Check: lint

[failure] 485-485:
Statement inside of curly braces should be on next line


[failure] 485-485:
Requires a space after '{'


[failure] 485-485:
Closing curly brace should be on the same line as opening curly brace or on the line after the previous block


[failure] 485-485:
Requires a space before '}'

@anishfyle anishfyle added deploy Triggers deployment of active branch to Staging and removed deploy Triggers deployment of active branch to Staging labels Jan 2, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.spec.ts (1)

518-518: Consider re-enabling this skipped test to maintain coverage and detect potential regressions.
Skipping this important test may reduce confidence in the CCC expense grouping logic.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 27d567c and 286d24f.

📒 Files selected for processing (2)
  • src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.spec.ts (1 hunks)
  • src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts (3 hunks)
🔇 Additional comments (6)
src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts (6)

4-4: Adding catchError to the imports looks good.
This import strengthens error-handling capabilities.


485-487: Fix the formatting of the error handling code block.
This comment has been flagged before in a past review; the block lacks spacing and line breaks, making it harder to read.

485   this.workspaceService.getWorkspaceGeneralSettings().pipe(catchError(error => {
-  return of(null);
+    return of(null);
}))

488-488: No issues found with adding employeeSettingService.getDistinctQBODestinationAttributes to forkJoin.
Good use of combining multiple observables.


493-493: Providing a default fallback for employee_field_mapping is a robust approach.
Ensures the component remains stable if this field is missing in the settings.


510-510: A default false for auto_map_employees is sensible if the property is undefined.
This patch ensures that the employee mapping form remains safe if no value is provided.


501-501: Verifying defaulting isImportItemsEnabled to false.
Confirm that disabling item imports by default won’t cause unexpected behavior for workspaces intended to use item imports.

✅ Verification successful

Defaulting isImportItemsEnabled to false is safe and consistent with the codebase

Based on the codebase analysis:

  • The isImportItemsEnabled flag is consistently initialized from workspaceGeneralSettings.import_items
  • The only conditional behavior dependent on this flag is:
    • Displaying additional warning content when switching to JOURNAL_ENTRY export type
    • Adjusting display names in the dashboard error section to include "Item" alongside "Account"
  • The default false value is already used in story files, indicating it's an expected default state
  • No code paths assume or require this flag to be true by default
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Confirm if any references assume `isImportItemsEnabled` is true by default.
rg -A 2 "isImportItemsEnabled"

Length of output: 7807

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/app/core/models/qbo/qbo-configuration/qbo-export-setting.model.ts (1)

261-261: Consider extracting fallback logic to a helper function for consistency.

Using a conditional access operator here ensures null safety, preventing potential runtime errors. For maintainability, you might extract the fallback logic to a helper function or a common config, making it easier to manage the default behavior across the codebase.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 286d24f and 68be07e.

📒 Files selected for processing (2)
  • src/app/core/models/qbo/qbo-configuration/qbo-export-setting.model.ts (1 hunks)
  • src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/integrations/qbo/qbo-shared/qbo-export-settings/qbo-export-settings.component.ts

@anishfyle anishfyle added deploy Triggers deployment of active branch to Staging and removed deploy Triggers deployment of active branch to Staging labels Jan 2, 2025
Copy link

github-actions bot commented Jan 2, 2025

Unit Test Coverage % values
Statements 33.22% ( 4119 / 12398 )
Branches 26.58% ( 1177 / 4428 )
Functions 25.75% ( 893 / 3467 )
Lines 33.4% ( 4053 / 12133 )

@anishfyle anishfyle merged commit 977e96c into master Jan 3, 2025
4 checks passed
anishfyle added a commit that referenced this pull request Jan 3, 2025
* feat: Travelperk Guard

* lint fix

* token guard

* lint fix

* fix

* pr comments

* make cacheable and catch error

* lint fix

* fixes for export settings wgs

* fix lint

* minor fixes for wgs

* fix tests

* skip flaky
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deploy Triggers deployment of active branch to Staging size/M Medium PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants